﻿using System;
using System.Drawing;
using Dataweb.NShape.Advanced;
using Dataweb.NShape;
using System.ComponentModel;
using cz.zcu.PreSti.Components;
using System.Collections.Generic;

namespace cz.zcu.PreSti.Shapes
{
    class MixerSymbol : RectangleBase, ISymbol
    {
        protected override void InitializeToDefault(IStyleSet styleSet)
        {
            base.InitializeToDefault(styleSet);
            PortCount = 4;
        }

        public override Shape Clone()
        {
            Shape result = new MixerSymbol(Type, (Template)null);
            result.CopyFrom(this);
            return result;
        }

        public override void CopyFrom(Shape source)
        {
            base.CopyFrom(source);
            if (source is MixerSymbol)
            {
                PortCount = ((MixerSymbol)source).PortCount;
            }
        }


        protected override int ControlPointCount
        {
            get { return ActionsCount + EventsCount + SettersCount + GettersCount; }
        }


        public override bool HasControlPointCapability(ControlPointId controlPointId, ControlPointCapabilities controlPointCapability)
        {
            if (controlPointId >= 0 && controlPointId <= ControlPointCount) return ((controlPointCapability & ControlPointCapabilities.Connect) != 0);
            else return false;
        }


        protected internal MixerSymbol(ShapeType shapeType, Template template)
            : base(shapeType, template)
        {
        }


        protected override void CalcControlPoints()
        {

            int left = (int)Math.Round(-Width / 2f);
            int top = (int)Math.Round(-Height / 2f);
            int right = left + Width;
            int bottom = top + Height;

            ControlPoints[portCount].X = right;
            ControlPoints[portCount].Y = top + Height / 2;
            ControlPoints[portCount + 1].X = 0;
            ControlPoints[portCount + 1].Y = (int)Math.Round((Height / 2 + 2 * connectorWidth) / 2d);
            for (int i = 0; i < portCount; i++)
            {
                ControlPoints[i].X = left;
                ControlPoints[i].Y = -connectorWidth * (portCount - 1) + i * connectorWidth * 2;
            }
        }


        protected override void CalcCaptionBounds(int index, out Rectangle captionBounds)
        {
            if (index != 0) throw new IndexOutOfRangeException();
            int left = (int)Math.Round(-Width / 2f);
            int top = (int)Math.Round(-Height / 2f);
            captionBounds = Rectangle.Empty;
            captionBounds.X = left;
            captionBounds.Y = top;
            captionBounds.Width = Width;
            captionBounds.Height = Height;
        }


        protected override bool CalculatePath()
        {
            if (base.CalculatePath())
            {
                int left = (int)Math.Round(-Width / 2f);
                int top = (int)Math.Round(-Height / 2f);
                int right = left + Width;
                int bottom = top + Height;

                PointF[] points = new PointF[3];
                points[0].X = left;
                points[0].Y = bottom;
                points[1].X = right;
                points[1].Y = 2 * connectorWidth;
                points[2].X = right;
                points[2].Y = -2 * connectorWidth;


                Path.Reset();
                Path.StartFigure();
                Path.AddLine(right, -2 * connectorWidth, left, top);
                Path.AddLines(points);
                for (int i = 0; i < portCount; i++)
                {
                    PointF[] a = { new PointF((float)left, top + Height / 2f - (connectorWidth * portCount) + (2 * i * connectorWidth)), new PointF(left + connectorWidth, top + Height / 2f - (connectorWidth * portCount) + connectorWidth + (2 * i * connectorWidth)), new PointF((float)left, top + Height / 2f - (connectorWidth * portCount) + 2 * connectorWidth + (2 * i * connectorWidth)) };
                    Path.AddPolygon(a);
                }
                PointF[] b = { new PointF(right, top + Height / 2f - connectorWidth), new PointF(right - connectorWidth, top + Height / 2f), new PointF(right, top + Height / 2f + connectorWidth) };
                Path.AddPolygon(b);
                Path.AddCurve(new PointF[] { new PointF(-4, bottom / 2 + connectorWidth), new PointF(0, bottom / 2 + connectorWidth - 4), new PointF(4, bottom / 2 + connectorWidth) }, 1);
                Path.CloseFigure();
                return true;
            }
            return false;
        }

        protected int PortCount
        {
            get { return portCount; }
            set
            {
                Invalidate();
                portCount = value;
                controlPoints = new Point[ControlPointCount];
                Height = (portCount + 1) * connectorWidth * 2;
                UpdateDrawCache();
                InvalidateDrawCache();
                Invalidate();
            }
        }


        #region Fields
        private int connectorWidth = 5;
        private int portCount = 4;
        #endregion


        #region ISymbol Members

        public BaseComponent initializeComponent(IPresentation p)
        {
            MixerModel model = (MixerModel)this.ModelObject;
            Mixer mixer = new Mixer(p);
            mixer.Values = model.Values;
            return mixer;
        }

        public virtual int ActionsCount
        {
            get { return portCount; }
        }

        public virtual int EventsCount
        {
            get { return 1; }
        }

        public virtual int SettersCount
        {
            get { return 0; }
        }

        public virtual int GettersCount
        {
            get { return 1; }
        }

        public virtual string GetTitleForAction(int id)
        {
            if (id >= 0 && id < portCount)
                return "Action for value '" + ((MixerModel)this.ModelObject).Values[id] + "'";
            if (id == portCount) return "Else part";
            return null;
        }

        public virtual string GetTitleForEvent(int id)
        {
            return null;
        }

        public string GetTitleForSetter(int id)
        {
            return null;
        }

        public string GetTitleForGetter(int id)
        {
            return "Value assigned to the action";
        }

        #endregion

        internal static Shape CreateInstance(ShapeType shapeType, Template template)
        {
            return new MixerSymbol(shapeType, template);
        }

    }
}

public class MixerModel : ModelObjectBase
{

    #region Fields
    private string[] values = new string[4] { "1", "2", "3", "4" };
    private char securityDomainName = 'A';

    private const int PropertyIdValues = 1;

    #endregion

    #region properties

    [Category("Presentation")]
    [Description("List of values for every action.")]
    [PropertyMappingId(PropertyIdValues)]
    [Editor(typeof(System.ComponentModel.Design.ArrayEditor), typeof(System.Drawing.Design.UITypeEditor))]
    public virtual string[] Values
    {
        get
        {
            return values;
        }
        set
        {
            values = value;
        }
    }

    #endregion

    public static MixerModel CreateInstance(ModelObjectType modelObjectType)
    {
        return new MixerModel(modelObjectType);
    }


    protected internal MixerModel(ModelObjectType modelObjectType)
        : base(modelObjectType)
    {
        this.terminalCount = 6;
    }


    protected internal MixerModel(MixerModel source)
        : base(source)
    {
        Values = source.Values;
        this.terminalCount = 6;
    }


    public override IModelObject Clone()
    {
        return new MixerModel(this);
    }


    public override IEnumerable<MenuItemDef> GetMenuItemDefs()
    {
        throw new NotImplementedException();
    }


    public override void Connect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
    {
    }


    public override void Disconnect(TerminalId ownTerminalId, IModelObject targetConnector, TerminalId targetTerminalId)
    {
    }

    public override char SecurityDomainName
    {
        get { return securityDomainName; }
        set
        {
            if (value < 'A' || value > 'Z')
                throw new ArgumentOutOfRangeException("SecurityDomainName", "The domain qualifier has to be an upper case  ANSI letter (A-Z).");
            securityDomainName = value;
        }
    }


    #region IEntity Members

    public static new IEnumerable<EntityPropertyDefinition> GetPropertyDefinitions(int version)
    {
        foreach (EntityPropertyDefinition pi in ModelObjectBase.GetPropertyDefinitions(version))
            yield return pi;
        yield return new EntityFieldDefinition("Values", typeof(string));
    }

    protected override void LoadFieldsCore(IRepositoryReader reader, int version)
    {
        int vali = 0;
        int vali2 = 0;
        int i = 0;
        base.LoadFieldsCore(reader, version);
        Values.Initialize();
        string vals = reader.ReadString();
        do
        {
            vali2 = vals.IndexOf("|", vali);
            if (vali2 == -1) break;
            Values[i] = vals.Substring(vali, vali2 - vali);
            vali = vali2 + 1;
            i++;
        } while (vals.Length != vali2 + 1);
    }

    protected override void SaveFieldsCore(IRepositoryWriter writer, int version)
    {
        string vals = "";
        base.SaveFieldsCore(writer, version);
        foreach (string v in values)
        {
            vals += v + "|";
        }
        writer.WriteString(vals);
    }

    #endregion

}

